package com.zee.admin.aspect;

import cn.hutool.core.collection.CollUtil;
import com.zee.admin.annotation.DataFilter;
import com.zee.admin.enums.SuperAdminEnum;
import com.zee.admin.interceptor.DataScope;
import com.zee.admin.shiro.AdminSecurityUser;
import com.zee.admin.shiro.AdminUserDetail;
import com.zee.common.model.dto.DataScopeDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

/**
 * 数据过滤，切面处理类
 *
 * @author Mark LinZee
 * @email LinZee666@163.com
 */
@Slf4j
@Aspect
@Component
public class DataFilterAspect {

    @Pointcut("@annotation(com.zee.admin.annotation.DataFilter)")
    public void dataFilterCut() {

    }

    @Before("dataFilterCut()")
    public void dataFilter(JoinPoint point) {
        AdminUserDetail user = AdminSecurityUser.getUser();
        //如果是超级管理员，则不进行数据过滤
        if (user.getSuperAdmin() == SuperAdminEnum.YES.value()) {
            return;
        }

        if (point.getArgs().length == 0) {
            throw new RuntimeException("需要传递参数");
        }

        Object params = point.getArgs()[0];
        try {
            if (params instanceof Map) {
                //参数是map类型
                Map map = (Map) params;
                String sqlFilter = getSqlFilter(user, point);
                map.put("dataScope", new DataScope(sqlFilter));

            } else if (params instanceof DataScope) {
                //单个对象，是DataScope类型的情况
                Class<?> clazz = params.getClass().getSuperclass();
                Field dataScopeField = clazz.getDeclaredField("dataScope");
                dataScopeField.setAccessible(true);

                String sqlFilter = getSqlFilter(user, point);
                dataScopeField.set(params, new DataScope(sqlFilter));

            } else if (DataScopeDTO.class.isAssignableFrom(params.getClass().getSuperclass())) {
                //单个对象，params继承至DataScopeDTO的情况
                Class<?> clazz = params.getClass().getSuperclass();
                Field dataScopeField = clazz.getDeclaredField("dataScope");
                dataScopeField.setAccessible(true);

                String sqlFilter = getSqlFilter(user, point);
                dataScopeField.set(params, new DataScope(sqlFilter));
            }
        } catch (Exception e) {
            log.error("{} 找不到dataScope字段，参数缺少DataScope类型", params.getClass().getName());
            e.printStackTrace();
        }
    }

    /**
     * 获取数据过滤的SQL
     */
    private String getSqlFilter(AdminUserDetail user, JoinPoint point) throws Exception {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = point.getTarget().getClass().getDeclaredMethod(signature.getName(), signature.getParameterTypes());
        DataFilter dataFilter = method.getAnnotation(DataFilter.class);

        //获取表的别名
        String tableAlias = dataFilter.tableAlias();
        if (StringUtils.isNotBlank(tableAlias)) {
            tableAlias += ".";
        }

        StringBuilder sqlFilter = new StringBuilder();
        sqlFilter.append(" (");

        //部门ID列表
        List<Integer> deptIdList = user.getDeptIdList();
        if (CollUtil.isNotEmpty(deptIdList)) {
            sqlFilter.append(tableAlias).append(dataFilter.deptId());

            sqlFilter.append(" in(").append(StringUtils.join(deptIdList, ",")).append(")");
        }

        //查询本人数据
        if (CollUtil.isNotEmpty(deptIdList)) {
            sqlFilter.append(" or ");
        }
        sqlFilter.append(tableAlias).append(dataFilter.userId()).append("=").append(user.getId());

        sqlFilter.append(")");

        return sqlFilter.toString();
    }
}